package risoe.syslab.fhnew.config;

import java.io.File;
import java.net.InetAddress;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class PlatformConfig {
	public static final String DEFAULT_CONFIGFILE = "conf/platform.xml";
	public static final String BUILDING_CONFIG_KEY = "building_config_path";

	private HashMap<String, String> mParameterMap;
	private String mHostName;
	private String mConfigFile;

	/**
	 * Parses a config file containing platform information (paths, RMI naming, etc.). 
	 * Passing null will result in the parsing of the default config file, i.e. platform.xml
	 * @param configFile the name of the config file to parse
	 * @return a PlatformConfig object that can be used to query parameters
	 */
	public PlatformConfig(String cfgfile) {
		HashMap<String, String> map = null;
		try {
			mHostName = InetAddress.getLocalHost().getHostName();
		} catch (Exception e) {
			// Will never happen
		}

		if (cfgfile == null) {
			System.out.println("No configuration file argument given - using default '"+DEFAULT_CONFIGFILE+"'.");
			mConfigFile = DEFAULT_CONFIGFILE;
		} else {
			System.out.println("Parsing config file: "+cfgfile);
			map = parseConfig(cfgfile);
			if (map == null) {
				System.out.println("Parsing of platform config file: "+cfgfile+" failed! Falling back to default file.");
				mConfigFile = DEFAULT_CONFIGFILE;
			} else {
				mConfigFile = cfgfile;
			}
		}

		if (map == null) {
			// Attempt default config
			map = parseConfig(mConfigFile);

			if (map == null) {
				// Parsing default config failed! Fallback
				System.out.println("Parsing of platform config file: "+mConfigFile+" failed!");
				map = new HashMap<String, String>();
			}
		} 
		
		// Ensure that the building_config_path parameter exists
		if (!map.containsKey(BUILDING_CONFIG_KEY)) {
			// No building config file detailed in the platform config file. Use default, i.e. building.xml.[hostname]
			System.out.println("No building_config_path key specified in: "+cfgfile+"! Falling back to default value");
			map.put(BUILDING_CONFIG_KEY, "building.xml."+mHostName);
		}

		mParameterMap = map;
	}

//	/**
//	 * Returns the value of the parameter associated with a key, falling back to a default value
//	 * based on host name if no such parameter exists
//	 * @param key the parameter to query
//	 * @return a String representing the value from the config file or a default value
//	 */
//	public String getParameter(String key) {
//		if (mParameterMap.containsKey(key)) {
//			return mParameterMap.get(key);
//		} else {
//			// Fallback to hostname
//			System.out.println("Missing parameter in platform config: "+mConfigFile+"! Falling back to default");
//			return key + mHostName;
//		}
//	}
	
	/**
	 * Returns the value of the parameter associated with a key, falling back to a provided default value
	 * @param key the parameter to query
	 * @param a defaultValue that is used if the parameter doesn't exist
	 * @return a String representing the value from the config file or a default value
	 */
	public String getParameter(String key, String defaultValue) {
		if (mParameterMap.containsKey(key)) {
			return mParameterMap.get(key);
		} else {
			// Fallback to provided value
			System.out.println("Missing parameter for key: "+key+" in platform config: "+mConfigFile+"! Falling back to default");
			return defaultValue;
		}
	}
	
	/**
	 * @return the hostname of localhost (this computer)
	 */
	public String getHostName() {
		return mHostName;
	}

	/**
	 * Parses a config file containing platform information (paths, RMI naming, etc.)
	 * @param configFile the name of the config file to parse
	 * @return a map of parameters and associated values or null if parsing failed
	 */
	private HashMap<String, String> parseConfig(String configFile) {
		try {
			DocumentBuilder builder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document document = builder.parse(new File(configFile));

			HashMap<String, String> map = new HashMap<String, String>();
			NodeList parameters = document.getElementsByTagName("parameter");
			for (int i=0; i<parameters.getLength(); i++) {
				String key = parameters.item(i).getAttributes().getNamedItem("key").getTextContent();
				String value = parameters.item(i).getAttributes().getNamedItem("value").getTextContent();
				map.put(key, value);
			}

			return map;
		}
		catch (Exception e) {
			return null;
		}
	}
}
